package com.hwtx.form.domain.handle.formconfig;

import com.google.common.collect.Maps;
import com.hwtx.form.domain.FormConstants;
import com.hwtx.form.domain.def.meta.Api;
import com.hwtx.form.domain.def.meta.Button;
import com.hwtx.form.domain.def.meta.Component;
import com.hwtx.form.domain.handle.i18n.I18nConfig;
import com.hwtx.form.domain.repo.FormConfigRepo;
import com.hwtx.form.ext.ChartConfigRepo;
import com.hwtx.form.persistence.entity.FormConfigTpl;
import com.hwtx.form.util.FormUtil;
import com.hwtx.form.util.JacksonUtil;
import io.geekidea.boot.auth.cache.LoginCache;
import io.geekidea.boot.config.properties.BootProperties;
import io.geekidea.boot.framework.exception.BusinessException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.hwtx.form.domain.FormConstants.FormLayout.*;
import static com.hwtx.form.domain.FormConstants.HTTP_GET;
import static com.hwtx.form.domain.FormConstants.HTTP_POST;
import static com.hwtx.form.util.FormUtil.*;

@Slf4j
@org.springframework.stereotype.Component
public class FormTplHandle {
    @Resource
    private FormConfigRepo formConfigRepo;
    @Resource
    private I18nConfig i18nConfig;
    @Resource
    private BootProperties bootProperties;
    @Resource
    private ChartConfigRepo chartConfigRepo;

    public String loadTpl(Map<String, Object> formData) {
        Integer tpl = getIntPostValue(formData, "tpl");
        if (tpl == null) {
            throw new BusinessException("模板不能为空");
        }
        FormConstants.FormLayout layout = FormConstants.FormLayout.of(tpl);
        if (layout == null) {
            throw new BusinessException("模板不存在");
        }
        String tplContent;
        try {
            tplContent = FileUtils.readFileToString(new File(FormUtil.getTplDir(), "formConfig-layout.json"), StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("读取模板文件失败", e);
            return "{}";
        }
        Long formId = getLongPostValue(formData, "formId");
        if (formId == null) {
            throw new BusinessException("表单不存在");
        }
        com.hwtx.form.domain.def.meta.Component.Form form = new com.hwtx.form.domain.def.meta.Component.Form();
        form.setWrapWithPanel(false);
        form.setInitApi(Api.builder().method(HTTP_GET).data(Map.of("fId", "${fId}", "formId", formId, "type", "tplExt", "valueIds", formId))
                .url(bootProperties.getDomain() + "/api/form/get").build());
        form.setApi(Api.builder().method(HTTP_POST).data(Map.of("fId", "${fId}", "formId", formId, "type", "ext", "&", "$$"))
                .url(bootProperties.getDomain() + "/api/form/update").build());
        List<com.hwtx.form.domain.def.meta.Component> components = new ArrayList<>();
        if (layout == FormConstants.FormLayout.LAYOUT_1) {
            components.add(getTplItem(tplContent, "明细", FormConstants.TplConfigKey.C1));
        } else if (layout == FormConstants.FormLayout.LAYOUT_2) {
            components.add(getTplItem(tplContent, "第一列", FormConstants.TplConfigKey.C1));
            components.add(getTplItem(tplContent, "第二列", FormConstants.TplConfigKey.C2));
        } else if (layout == FormConstants.FormLayout.LAYOUT_3) {
            components.add(getTplItem(tplContent, "第一列", FormConstants.TplConfigKey.C1));
            components.add(getTplItem(tplContent, "第二列", FormConstants.TplConfigKey.C2));
            components.add(getTplItem(tplContent, "第三列", FormConstants.TplConfigKey.C3));
        } else if (layout == FormConstants.FormLayout.LAYOUT_4) {
            components.add(getTplItem(tplContent, "第一行", FormConstants.TplConfigKey.R1));
            components.add(getTplItem(tplContent, "第一列", FormConstants.TplConfigKey.C1));
            components.add(getTplItem(tplContent, "第二列", FormConstants.TplConfigKey.C2));
        } else if (layout == FormConstants.FormLayout.LAYOUT_5) {
            components.add(getTplItem(tplContent, "第一行", FormConstants.TplConfigKey.R1));
            components.add(getTplItem(tplContent, "第一列", FormConstants.TplConfigKey.C1));
            components.add(getTplItem(tplContent, "第二列", FormConstants.TplConfigKey.C2));
            components.add(getTplItem(tplContent, "第三列", FormConstants.TplConfigKey.C3));
        }
        Button submit = new Button();
        submit.setType("submit");
        submit.setLevel("primary");
        submit.setLabel("#i18n{submit}");
        components.add(submit);
        form.setBody(components);
        return i18nConfig.handlePageI18n(JacksonUtil.object2json(form), getLocale(formData));
    }

    public Map<String, Object> getTplConfig(Long formId) {
        FormConfigTpl formConfigTpl = formConfigRepo.getFormTplConfig(formId);
        String config = formConfigTpl.getConfig();
        if (StringUtils.isNotEmpty(config)) {
            return JacksonUtil.json2Map(config);
        }
        return Maps.newHashMap();
    }

    private com.hwtx.form.domain.def.meta.Component getTplItem(String tpl, String title, FormConstants.TplConfigKey key) {
        String json = tpl.replace("#title#", title)
                .replaceAll("@form.app.domain@", bootProperties.getDomain())
                .replaceAll("#configInfo#", key.getKey())
                .replace("#action#", key.getAction())
                .replace("#init#", key.getInit());
        com.hwtx.form.domain.def.meta.Component.JsonContent jsonContent = new com.hwtx.form.domain.def.meta.Component.JsonContent();
        jsonContent.setContent(json);
        return jsonContent;
    }

    public boolean saveTplConfig(Long formId, FormConstants.FormLayout formLayout, Map<String, Object> data) {
        FormConfigTpl formConfigTpl = formConfigRepo.getFormTplConfig(formId);
        if (formConfigTpl == null) {
            formConfigTpl = new FormConfigTpl();
            formConfigTpl.setFormId(formId);
            formConfigTpl.setTpl(formLayout.getCode());
            formConfigTpl.setConfig(JacksonUtil.object2json(buildTplConfig(formLayout, data)));
            formConfigTpl.setCreateTime(new java.util.Date());
            formConfigTpl.setCreateId(LoginCache.get().getUsername());
            formConfigTpl.setUpdateTime(new java.util.Date());
            formConfigTpl.setUpdateId(LoginCache.get().getUsername());
            return formConfigRepo.saveFormTplConfig(formConfigTpl);
        } else {
            formConfigTpl.setTpl(formLayout.getCode());
            formConfigTpl.setConfig(JacksonUtil.object2json(buildTplConfig(formLayout, data)));
            formConfigTpl.setUpdateTime(new java.util.Date());
            formConfigTpl.setUpdateId(LoginCache.get().getUsername());
            return formConfigRepo.updateFormTplConfig(formConfigTpl);
        }
    }

    private Map<String, Object> buildTplConfig(FormConstants.FormLayout formLayout, Map<String, Object> data) {
        Map<String, Object> ret = Maps.newHashMap();
        if (formLayout == LAYOUT_1) {
            buildTplItem(FormConstants.TplConfigKey.C1, data, ret);
        } else if (formLayout == LAYOUT_2) {
            buildTplItem(FormConstants.TplConfigKey.C1, data, ret);
            buildTplItem(FormConstants.TplConfigKey.C2, data, ret);
        } else if (formLayout == LAYOUT_3) {
            buildTplItem(FormConstants.TplConfigKey.C1, data, ret);
            buildTplItem(FormConstants.TplConfigKey.C2, data, ret);
            buildTplItem(FormConstants.TplConfigKey.C3, data, ret);
        } else if (formLayout == LAYOUT_4) {
            buildTplItem(FormConstants.TplConfigKey.C1, data, ret);
            buildTplItem(FormConstants.TplConfigKey.C2, data, ret);
            buildTplItem(FormConstants.TplConfigKey.R1, data, ret);
        } else if (formLayout == LAYOUT_5) {
            buildTplItem(FormConstants.TplConfigKey.C1, data, ret);
            buildTplItem(FormConstants.TplConfigKey.C2, data, ret);
            buildTplItem(FormConstants.TplConfigKey.C3, data, ret);
            buildTplItem(FormConstants.TplConfigKey.R1, data, ret);
        }
        return ret;
    }

    private void buildTplItem(FormConstants.TplConfigKey key, Map<String, Object> data, Map<String, Object> ret) {
        ret.put(key.getKey(), data.get(key.getKey()));
        ret.put(key.getAction(), data.get(key.getAction()));
        ret.put(key.getInit(), data.get(key.getInit()));
    }

    public String ctrlConfig(Map<String, Object> formData) {
        Integer ctrlConfig = getIntPostValue(formData, "ctrlConfig");
        Long formId = getLongPostValue(formData, "formId");
        if (ctrlConfig == null || formId == null) {
            return "{}";
        }
        FormConstants.FormComponentType componentType = FormConstants.FormComponentType.of(ctrlConfig);
        if (componentType == null) {
            return "{}";
        }
        Component.Form form = new Component.Form();
        form.setWrapWithPanel(false);
        Component.Panel panel = new Component.Panel();
        panel.setTitle("配置属性");
        form.setBody(List.of(panel));
        List<Component> components = Lists.newArrayList();
        if (componentType == FormConstants.FormComponentType.LINE_CHART) {
            components.addAll(chartConfigRepo.getDefaultLineChartConfig()
                    .stream().map(config -> Component.Input.getText(config.getRemark(), config.getCKey(), "")).toList());
        } else if (componentType == FormConstants.FormComponentType.PIE_CHART) {
            components.addAll(chartConfigRepo.getDefaultPieChartConfig()
                    .stream().map(config -> Component.Input.getText(config.getRemark(), config.getCKey(), "")).toList());
        }
        Component.Group.groupComponents(LAYOUT_2, panel, components);
        return JacksonUtil.object2json(form);
    }
}
